package com.cz.zslu.controller;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.cz.zslu.entity.SysUser;
import com.cz.zslu.service.IBaseAttachmentService;
import com.cz.zslu.rest.BaseController;
import com.cz.zslu.service.ISysUserService;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import com.cz.zslu.common.ReturnObject;
import com.cz.zslu.entity.BaseAttachment;
import com.cz.zslu.interceptor.BaseContextHandler;
import com.cz.zslu.interceptor.IgnoreAuth;
import sun.misc.BASE64Decoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 文件操作api
 * 上传采用断点续传的方式， 可后台直接上传
 * 不用等图片传好了在提交了，可以先提交，然后后台慢慢传图片
 **/
@RestController
@RequestMapping("/file")
@Api(description = "文件操作api")
public class FileOperateApi extends BaseController<IBaseAttachmentService, BaseAttachment> {

    /**
     * 文件路径
     */
    @Value("${file_address}")
    private String storePath;

    @Autowired
    private ISysUserService iSysUserService;

    //private String storePath = "/Users/zhurusen/Workspaces/upload/";


    /**
     * 富文本文件上传
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @IgnoreAuth
    @ApiOperation("富文本文件上传")
    @RequestMapping(value = "/layeditUplode", method = RequestMethod.POST)
    public ReturnObject layeditUplode(HttpServletRequest request, HttpServletResponse
            response) throws IOException {

        //获取文件保存目录
        String path = storePath + "layedit/";
        //创建文件目录
        new File(path).mkdirs();
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;

        Iterator<String> iter = multipartRequest.getFileNames();
        while (iter.hasNext()) {
            MultipartFile file = multipartRequest.getFile(iter.next());
            //文件名
            String fileName = file.getOriginalFilename();
            //文件后缀名
            String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1,
                    fileName.length());
            //生成新新文件名
            String attName = System.currentTimeMillis() + "." + fileExt;
            // 上传文件
            File uploadFile = new File(path + attName);
            FileCopyUtils.copy(file.getBytes(), uploadFile);
            //保存文件
            BaseAttachment info = new BaseAttachment(null, null, 0, fileName, attName, "/layedit/" + attName,
                    fileExt, Long.toString(file.getSize()), null, null, null, "1");
            baseService.insert(info);
            Map map = Maps.newHashMap();
            map.put("src", "http://www.ziselu.com/zsl/file/" + info.getAddress());
            return new ReturnObject(0, "上传成功", map);

        }
        return new ReturnObject<>(0, "上传成功");
    }

    /**
     * 申请文件上传key
     *
     * @return
     */
    @ApiOperation("申请文件上传key（app专用）")
    @RequestMapping(value = "/applyFileKey", method = RequestMethod.POST)
    public ReturnObject<List<BaseAttachment>> applyFileKey(@ApiParam("上传文件文件名") String[] fileNames, @ApiParam
            ("附件类型(VERSION(版本附件)、USER(人员表))") String type, @ApiParam("关联信息id") Long theirId) {
        List<BaseAttachment> list = new ArrayList<>();
        int i = 1;
        for (String fileName : fileNames) {
            if (StringUtils.isNotBlank(fileName)) {
                if (fileName.lastIndexOf(".") < 0) {
                    return new ReturnObject(1, "文件名称异常");
                }
                //文件后缀名
                String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
                //生成新新文件名
                String attName = System.currentTimeMillis() + i + "." + fileExt;
                //文件存放路径
                String address = "/" + BaseContextHandler.getUsername();
                //创建文件目录
                new File(storePath + address).mkdirs();
                //新增附件
                list.add(new BaseAttachment(type, theirId, 0, fileName, attName, address + "/" + attName,
                        fileExt, null, null, null, null, "0"));
            }
            i++;
        }
        //保存
        baseService.insertBatch(list);
        return new ReturnObject(0, "", list);
    }

    @IgnoreAuth
    @ApiOperation("文件上传（app专用）")
    @RequestMapping(value = "/fileUpload", method = RequestMethod.POST)
    public ReturnObject fileUpload(@ApiParam("文件key") Long[] fileKeys, HttpServletRequest request, HttpServletResponse
            response) throws IOException {
        // 务必，防止返回文件名是乱码
        response.setCharacterEncoding("utf-8");
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        List<MultipartFile> iter = multipartRequest.getFiles("file");
        int i = 0;
        for (MultipartFile file : iter) {
            //判断文件是否已上传
            BaseAttachment info = baseService.selectById(fileKeys[i]);
            if (info == null || info.getUploadState().equals("1") || !file.getOriginalFilename()
                    .equals(info.getOriginalName())) {
                continue;
            }
            info.setSize(Long.toString(file.getSize()));
            // 上传文件
            File uploadFile = new File(storePath + info.getAddress());
            FileCopyUtils.copy(file.getBytes(), uploadFile);
            //图片上传成功修改状态
            info.setUploadState("1");
            baseService.updateById(info);
            i++;
        }
        return new ReturnObject(0, "上传成功");
    }


    /**
     * 上传文件
     */
    @IgnoreAuth
    @ApiOperation("附件上传")
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public ReturnObject<BaseAttachment> appUpload(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            // 务必，防止返回文件名是乱码
            response.setCharacterEncoding("utf-8");
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
            Iterator<String> iter = multipartRequest.getFileNames();

            while (iter.hasNext()) {
                MultipartFile file = multipartRequest.getFile(iter.next());
                BaseAttachment info = new BaseAttachment();


                if (file.isEmpty()) {
                    return new ReturnObject(1, "上传文件不能为空");
                }


                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
                String ymd = sdf.format(new Date());


                String savePath = storePath;

                /**
                 *  文件大小
                 */
                Long fileSize = file.getSize();

                info.setSize(fileSize.toString());
                if (fileSize > 100000000) {
//            throw new Exception("上传失败：文件大小不能超过10M");
                    return new ReturnObject(1, "上传失败：文件大小不能超过100M");
                }

                /**
                 * 得到文件名称
                 */
                String fileName = file.getOriginalFilename();
                info.setOriginalName(fileName);

                String newFileName = "";
                String fileExt = "";

                String saveFileName = ymd;

                savePath += File.separator + ymd + File.separator;
                File dirFile = new File(savePath);
                if (!dirFile.exists()) {
                    dirFile.mkdirs();
                }


                if (fileSize > 0) {
                    try {
                        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
                        /**
                         *  文件后缀
                         */
                        fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();


                        info.setFileExt(fileExt);
                        /**
                         * 重定义文件名
                         */
                        newFileName = df.format(new Date()) + "_" + new Random().nextInt(1000) + "." + fileExt;

                        info.setAttName(newFileName);
                        SaveFileFromInputStream(file.getInputStream(), savePath, newFileName);


                    } catch (IOException e) {
                        e.printStackTrace();
                        return null;
                    }
                } else {
                    return new ReturnObject(1, "上传失败：上传文件不能为空");
                }


                /**
                 * 保存入库
                 */
                saveFileName += File.separator + newFileName;

                info.setAddress(saveFileName);
                baseService.insert(info);

                return new ReturnObject(0, "上传成功", info);
            }

        } catch (Exception e) {
            e.printStackTrace();
            return new ReturnObject(1, "系统偷懒了");

        }
        return new ReturnObject(1, "系统偷懒了");
    }

    /**
     * 查询文件
     *
     * @param id
     * @return
     */
    @ApiOperation("查看附件")
    @RequestMapping(value = "/seekFile/{id}", method = RequestMethod.GET)
    @IgnoreAuth
    public ResponseEntity<byte[]> seekFile(@PathVariable Long id) throws IOException {
        BaseAttachment info = baseService.selectById(id);
        File file = new File(storePath + info.getAddress());
        HttpHeaders headers = new HttpHeaders();
        headers.setContentDispositionFormData("fileName", file.getName());
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        ResponseEntity<byte[]> result = new ResponseEntity<>(FileUtils.readFileToByteArray(file), headers,
                HttpStatus.OK);
        return result;
    }


    public void SaveFileFromInputStream(InputStream stream, String path, String filename) throws IOException {
        FileOutputStream fs = new FileOutputStream(path + filename);
        byte[] buffer = new byte[1024 * 1024];
        int bytesum = 0;
        int byteread = 0;
        while ((byteread = stream.read(buffer)) != -1) {
            bytesum += byteread;
            fs.write(buffer, 0, byteread);
            fs.flush();
        }
        fs.close();
        stream.close();
    }

    /**
     * 图片裁剪后上传到服务器
     *
     * @param tailorString
     * @return
     */
    @IgnoreAuth
    @ApiOperation("上传裁剪图片")
    @RequestMapping(value = "/uploadTailorImg", method = RequestMethod.POST)
    public ReturnObject uploadTailorImg(@ApiParam("文件流") String tailorString) {
        BaseAttachment info = new BaseAttachment();
        try {
            tailorString = tailorString.replace(" ", "+");
            BASE64Decoder decoder = new sun.misc.BASE64Decoder();
            byte[] bytes1 = decoder.decodeBuffer(tailorString);
            for (int i = 0; i < bytes1.length; i++) {
                if (bytes1[i] < 0) {
                    //调整异常数据
                    bytes1[i] += 256;
                }
            }

            //保存路径
            String savePath = storePath;

            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
            String ymd = sdf.format(new Date());

            savePath += File.separator + ymd + File.separator;
            //定义图片名称
            String newFileName = "";
            //图片后缀
            String fileExt = "jpg";
            //保存入库的名称
            String saveFileName = "";
            //文件大小
            Long fileSize = null;
            //生成图片名称
            SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
            newFileName = df.format(new Date()) + "_" + new Random().nextInt(1000) + "." + fileExt;
            info.setAttName(newFileName);


            File file = new File(savePath, newFileName);

            if (!file.exists()) {
                file.mkdirs();
            }

            //先写入文件
            FileOutputStream out = new FileOutputStream(file);
            out.write(bytes1);
            out.flush();
            out.close();
            if (file.exists() && file.isFile()) {
                //读文件大小
                FileInputStream fis = new FileInputStream(file);
                fileSize = fis.getChannel().size();
                if (fileSize > 1000000) {
//             throw new Exception("上传失败：文件大小不能超过10M");
                    return new ReturnObject(1, "上传失败：文件大小不能超过1M");
                }
                if (fileSize != null) {

                    info.setSize(fileSize.toString());
                }
                fis.close();
            }else {
                return new ReturnObject(1, "上传失败：文件不能为空");
            }

            /**
             * 保存入库
             */
            saveFileName += File.separator + newFileName;

            info.setAddress(saveFileName);
            baseService.insert(info);

            //更新用户头像
            SysUser sysUser = iSysUserService.selectById(BaseContextHandler.getUserID());
            sysUser.setHeadPortraits(info.getAddress());
            iSysUserService.updateById(sysUser);

            return new ReturnObject(0, "更新成功");
        } catch (IOException e) {
            e.printStackTrace();
            return new ReturnObject(1, "更新失败");
        }

    }


}
